#include "stdafx.h"
#include "dispTestObject.h"
#include "dispIdManager.h"
#include "java.h"
#include "jtf.h"
#include "jniString.h"
#include "customException.h"
#include <string>
#include <sstream>

ULONG __stdcall CDispatchImpl::AddRef()
{
  return InterlockedIncrement(&mRefCount) ;
}

ULONG __stdcall CDispatchImpl::Release() 
{
  if (InterlockedDecrement(&mRefCount) == 0)
  {
    delete this ;
    return 0 ;
  }
  return mRefCount ;
}

STDMETHODIMP CDispatchImpl::QueryInterface(const IID& iid, void** ppv)
{    
  if (iid == IID_IUnknown || iid == IID_IDispatch)
  {
    *ppv = static_cast<CDispatchImpl*>(this) ; 
  }
  else
  {
    *ppv = NULL ;
    return E_NOINTERFACE ;
  }
  reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
  return S_OK ;
}

STDMETHODIMP CDispatchImpl::GetTypeInfoCount(UINT* pctinfo)
{
  *pctinfo = 0;
  return S_OK;
}

STDMETHODIMP CDispatchImpl::GetTypeInfo
(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
  return E_NOTIMPL;
}

STDMETHODIMP CDispatchImpl::GetIDsOfNames
(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
 LCID lcid, DISPID* rgdispid)
{
  for (UINT i = 0; i < cNames; i++)
  {
    rgdispid[i] = CDispatchIdManager::GetId(rgszNames[i]);
  }
  return S_OK;
}

STDMETHODIMP CDispatchImpl::Invoke(DISPID dispidMember, REFIID riid,
                                   LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
                                   EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
  try
  {
    // value
    if (dispidMember == 0)
    {
      pvarResult->vt = VT_BSTR;
      pvarResult->bstrVal = ToString();
      return S_OK;
    }
    HRESULT hr = E_NOTIMPL;
    std::wstring strDispatchName = CDispatchIdManager::DispIdToName(dispidMember);
    // method invokation
    if (wFlags & DISPATCH_METHOD)
    {
      hr = InvokeDynamicMethod(strDispatchName, pdispparams, pvarResult, pexcepinfo, puArgErr);
    }
    // property access
    if (!SUCCEEDED(hr) && (wFlags & DISPATCH_PROPERTYGET))
    {
      hr = GetDynamicProperty(strDispatchName, pdispparams, pvarResult, pexcepinfo, puArgErr);
    }
    else if (wFlags & DISPATCH_PROPERTYPUT)
    {
      hr = SetDynamicProperty(strDispatchName, pdispparams, pvarResult, pexcepinfo, puArgErr);
    }
    return hr;
  }
  catch (CustomException e)
  {
    if (pexcepinfo)
    {
      pexcepinfo->wCode = e.iCode;
      pexcepinfo->bstrSource = SysAllocString(e.strSource.c_str());
      pexcepinfo->bstrDescription = SysAllocString(e.strDescription.c_str());
      pexcepinfo->bstrHelpFile = NULL;
      pexcepinfo->dwHelpContext = NULL;
      pexcepinfo->pvReserved = 0;
      pexcepinfo->wReserved = 0;
      pexcepinfo->scode = 0;
      return DISP_E_EXCEPTION;
    }
    else
    {
      return E_FAIL;
    }
  }
}
